package snmp

import (
	"fmt"
	"math"
	"pids-cloud-server/entity"
	"pids-cloud-server/logging"
	"strings"

	"github.com/gosnmp/gosnmp"
)

// SnmpServerDataAcquisition /*服务器采集snmp实现*/
type SnmpWindowsDataAcquisition struct {
	SnmpDataAcquisition
}

// AcquireMemoryUsage /*采集内存、磁盘使用情况*/
func (s *SnmpWindowsDataAcquisition) AcquireMemoryAndStorageUsage(snmpOidMap map[string]entity.SnmpOid) (MemoryInfo, StorageDto, error) {
	var storageDto StorageDto
	var pathStorageDtos []PathStorageDto
	var uesdStorageSum int64 = 0
	var totalStorageSum int64 = 0
	var memoryTotal int = 0
	var memoryUsage float64 = 0
	// 使用已建立的 SNMP 客户端连接
	g := s.Snmpclient
	/*	result, err := g.Get([]string{snmpOidMap[MEMORY_TOTAL].OidValue})
		if err != nil {
			logging.Error("SNMP get MemoryUsage error:", err)
			memoryTotal = result.Variables[0].Value.(int)
		}*/
	descrList, err := g.BulkWalkAll(snmpOidMap[STORGE_DESCR].OidValue)
	if err != nil {
		return MemoryInfo{}, StorageDto{}, fmt.Errorf("failed to perform BulkWalk for storage description:%v", err)
	}
	unitList, err := g.BulkWalkAll(snmpOidMap[STORAGE_ALLOCATION_UNITS].OidValue)
	if err != nil {
		return MemoryInfo{}, StorageDto{}, fmt.Errorf("failed to perform BulkWalk for storage allocation units:: %v", err)
	}
	storageSizeList, err := g.BulkWalkAll((snmpOidMap[STORAGE_SIZE].OidValue))
	if err != nil {
		return MemoryInfo{}, StorageDto{}, fmt.Errorf("failed to perform BulkWalk for storage size:: %v", err)
	}
	usedStorageList, err := g.BulkWalkAll((snmpOidMap[STORAGE_USED].OidValue))
	if err != nil {
		return MemoryInfo{}, StorageDto{}, fmt.Errorf("failed to perform BulkWalk for storage used:: %v", err)
	}
	unitMap := make(map[int]int)
	for index, pdu := range unitList {
		unitMap[index] = pdu.Value.(int)
	}

	storageSizeMap := make(map[int]int)
	for index, pdu := range storageSizeList {
		storageSizeMap[index] = pdu.Value.(int)
	}

	usedStorageSizeMap := make(map[int]int)
	for index, pdu := range usedStorageList {
		usedStorageSizeMap[index] = pdu.Value.(int)
	}
	for index, pdu := range descrList {
		descStr := string(pdu.Value.([]byte))
		if descStr == "Physical Memory" {
			memoryUsed := usedStorageSizeMap[index] * unitMap[index]
			memoryTotal = storageSizeMap[index] * unitMap[index]
			memoryUsage = math.Round(float64(memoryUsed)/float64(memoryTotal)*100*100) / 100
		}
		if descStr == "" {
			continue
		}
		if strings.Contains(descStr, ":\\") {
			usedStoreageSize := int64(usedStorageSizeMap[index]) * int64(unitMap[index])
			totalStorageSize := int64(storageSizeMap[index]) * int64(unitMap[index])
			availStorageSize := totalStorageSize - usedStoreageSize
			if totalStorageSize <= 0 {
				continue
			}
			useage := math.Round(float64(usedStoreageSize)/float64(totalStorageSize)*100*100) / 100

			//大于1G的才采集，总体使用率统计不影响
			if totalStorageSize > 1024*1024*1024 {
				pathStorageDto := PathStorageDto{
					Path:      descStr,
					TotalSize: totalStorageSize,
					AvailSize: availStorageSize,
					UsedSize:  usedStoreageSize,
					Useage:    useage,
				}
				pathStorageDtos = append(pathStorageDtos, pathStorageDto)
			}
			uesdStorageSum += usedStoreageSize
			totalStorageSum += totalStorageSize
		}
	}
	totalUseage := math.Round(float64(uesdStorageSum)/float64(totalStorageSum)*100*100) / 100
	storageDto = StorageDto{
		PathStorages: pathStorageDtos,
		TotalSize:    totalStorageSum,
		AvailSize:    totalStorageSum - uesdStorageSum,
		UsedSize:     uesdStorageSum,
		Usage:        totalUseage}
	return MemoryInfo{memoryTotal / 1024, 0, 0, 0, 0, memoryUsage}, storageDto, nil
}

// AcquireCpu /*采集CPU信息*/
func (s *SnmpWindowsDataAcquisition) AcquireCpu(snmpOidMap map[string]entity.SnmpOid) (float64, error) {
	oidValue := snmpOidMap[CPU_USAGE].OidValue
	g := s.Snmpclient
	result, err := g.WalkAll(oidValue) // Walk 获取多个 CPU 的负载
	if err != nil {
		logging.Error("SNMP get CPU error:", err)
		return 0, fmt.Errorf("failed to get SNMP OIDs: %v", err)
	}
	var totalLoad int
	var cpuCount int

	for _, variable := range result {
		if variable.Type == gosnmp.Integer {
			cpuLoad := gosnmp.ToBigInt(variable.Value).Int64()
			totalLoad += int(cpuLoad)
			cpuCount++
		}
	}

	if cpuCount == 0 {
		return 0, fmt.Errorf("没有找到任何 CPU 使用率信息")
	}

	// 返回平均 CPU 使用率
	averageLoad := float64(totalLoad) / float64(cpuCount)
	return averageLoad, nil
}

// AcquireDisk /*采集磁盘使用情况*/
func (s *SnmpWindowsDataAcquisition) AcquireDisk(snmpOidMap map[string]entity.SnmpOid) (StorageDto, error) {
	var storageDto StorageDto
	var pathStorageDtos []PathStorageDto
	var uesdStorageSum int64 = 0
	var totalStorageSum int64 = 0

	g := s.Snmpclient
	descrList, err := g.BulkWalkAll(snmpOidMap[STORGE_DESCR].OidValue)
	if err != nil {
		return storageDto, fmt.Errorf("failed to perform BulkWalk for storage description: %v", err)
	}
	unitList, err := g.BulkWalkAll(snmpOidMap[STORAGE_ALLOCATION_UNITS].OidValue)
	if err != nil {
		return storageDto, fmt.Errorf("failed to perform BulkWalk for storage allocation units:: %v", err)
	}
	storageSizeList, err := g.BulkWalkAll((snmpOidMap[STORAGE_SIZE].OidValue))
	if err != nil {
		return storageDto, fmt.Errorf("failed to perform BulkWalk for storage size:: %v", err)
	}
	usedStorageList, err := g.BulkWalkAll((snmpOidMap[STORAGE_USED].OidValue))
	if err != nil {
		return storageDto, fmt.Errorf("failed to perform BulkWalk for storage used:: %v", err)
	}
	// Process the results
	unitMap := make(map[int]int)
	for index, pdu := range unitList {
		unitMap[index] = pdu.Value.(int)
	}

	storageSizeMap := make(map[int]int)
	for index, pdu := range storageSizeList {
		storageSizeMap[index] = pdu.Value.(int)
	}

	usedStorageSizeMap := make(map[int]int)
	for index, pdu := range usedStorageList {
		usedStorageSizeMap[index] = pdu.Value.(int)
	}
	for index, pdu := range descrList {
		descStr := string(pdu.Value.([]byte))
		if descStr == "" {
			continue
		}
		if strings.Contains(descStr, "/") {
			usedStoreageSize := int64(usedStorageSizeMap[index]) * int64(unitMap[index])
			totalStorageSize := int64(storageSizeMap[index]) * int64(unitMap[index])
			availStorageSize := totalStorageSize - usedStoreageSize
			if totalStorageSize <= 0 {
				continue
			}
			useage := math.Round(float64(usedStoreageSize)/float64(totalStorageSize)*100*100) / 100

			//大于1G的才采集，总体使用率统计不影响
			if totalStorageSize > 1024*1024*1024 {
				pathStorageDto := PathStorageDto{
					Path:      descStr,
					TotalSize: totalStorageSize,
					AvailSize: availStorageSize,
					UsedSize:  usedStoreageSize,
					Useage:    useage,
				}
				pathStorageDtos = append(pathStorageDtos, pathStorageDto)
			}
			uesdStorageSum += usedStoreageSize
			totalStorageSum += totalStorageSize
		}
	}

	totalUseage := math.Round(float64(uesdStorageSum)/float64(totalStorageSum)*100*100) / 100
	storageDto = StorageDto{
		PathStorages: pathStorageDtos,
		TotalSize:    totalStorageSum,
		AvailSize:    totalStorageSum - uesdStorageSum,
		UsedSize:     uesdStorageSum,
		Usage:        totalUseage}
	return storageDto, nil
}
